package dao;

import bean.Evento;
import bean.Usuario;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

/**
 * Pseudo DAO (Data Access Objetc) para realizar as operações de CRUD - expressão em língua 
 * IInglesa Create, Retrieve, Update e Delete.
 * <h1>ATENÇÃO! Para simplificar o entendimento, não foi aplicada o real pattern DAO!!!!</h1>
 * @author mertins
 */
public class EventoDAO {

    private Connection conexao;

    /**
     * Construtor único, para garantir a existência de uma conexão com um SGBD
     * @param conexao Connection já aberta com um SGBD
     */
    public EventoDAO(Connection conexao) {
        this.conexao = conexao;
    }

    /**
     * Se o funcioanário for válido, este método irá fazer o INSERT no SGBD.
     * O Código será inserido pela Sequência e será colocado novamente no objeto Funcionário.
     * @param func Funcionario a ser inserido
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public void create(Evento evt) throws SQLException {
        if (this.valida(evt)) {
            String sql = " INSERT INTO EVENTO(COD, DESCRICAO, DT, CODUSR) "
                    + " VALUES (NEXTVAL('SEQEVENTO'), ?, ?, ?)";
            PreparedStatement pst = this.conexao.prepareStatement(sql);
            //pst.setInt(1, evt.getCod());
            pst.setString(1, evt.getDescricao());
            java.sql.Date dtSQL = new java.sql.Date(evt.getDt().getTime());
            pst.setDate(2, dtSQL);
            Usuario usu = new Usuario();
            usu = evt.getCodusr();
            pst.setInt(3, usu.getCoduser());
            pst.executeUpdate();
            Statement st = this.conexao.createStatement();
            ResultSet rs = st.executeQuery("SELECT CURRVAL('SEQEVENTO')");
            if (rs.next()) {
                evt.setCod(rs.getInt(1));
            }
            rs.close();
            st.close();
            pst.close();
        }
    }

    /**
     * Retorna o funcionario do SGBD de acordo com o código do funcionario recebido.
     * @param func Funcionario a ser carregado do SGBD
     * @return Funcionario do SGBD
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    //cod,descricao,dt,codusr
    public Evento retrieve(Evento evt) throws SQLException {
        Evento evtRet = null;
        String sql = "SELECT COD, DESCRICAO, DT, CODUSR FROM EVENTO WHERE COD=?";
        PreparedStatement pst = this.conexao.prepareStatement(sql);
        pst.setInt(1, evt.getCod());
        ResultSet rs = pst.executeQuery();
        if (rs.next()) {
            evtRet = new Evento();
            evtRet.setCod(rs.getInt("COD"));
            evtRet.setDescricao(rs.getString("DESCRICAO"));
            evtRet.setDt(rs.getDate("DT"));
            
            UsuarioDAO usrDAO = new UsuarioDAO(conexao);
            Usuario usr = new Usuario();
            usr.setCoduser(rs.getInt("CODUSR"));
            usr = usrDAO.retrieve(usr);
            evtRet.setCodusr(usr);
            
        }
        rs.close();
        pst.close();
        return evtRet;
    }

    /**
     * Atualiza o funcionario no SGBD.
     * @param evt Funcionario a ser atualizado do SGBD
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public void update(Evento evt) throws SQLException {
        if (this.valida(evt)) {
            String sql = "UPDATE EVENTO SET DESCRICAO=?, DT=?, CODUSR=? WHERE  COD=?";
            PreparedStatement pst = this.conexao.prepareStatement(sql);
            pst.setString(1, evt.getDescricao());
            pst.setDate(2, (Date) evt.getDt());
          //pst.setDate(3, new java.sql.Date(func.getDtContratacao().getTime()));
            if (evt.getCodusr()== null) {
                pst.setNull(3, Types.NUMERIC);
            } else {
                pst.setLong(3, evt.getCodusr().getCoduser());
            }
            pst.setInt(4, evt.getCod());
            pst.executeUpdate();
            pst.close();
        }
    }

    /**
     * Remove o código do funcionario do SGBD.
     * @param func Funcionario a ser excluído. Necessita apenas do atributo COD
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public void delete(Evento evt) throws SQLException {
        String sql = "DELETE FROM EVENTO WHERE COD=?";
        PreparedStatement pst = this.conexao.prepareStatement(sql);
        pst.setInt(1, evt.getCod());
        pst.executeUpdate();
        pst.close();
    }

    /**
     * Retorna uma Lista com todos os Funcionarios cadastrados no SGBD.
     * @return Lista com os funcionarios.
     * @throws java.sql.SQLException Qualquer erro entre o Sistema e o Banco será devolvido nesta Exceção
     */
    public List<Evento> listaTodos() throws SQLException {
        List<Evento> lista = new ArrayList<Evento>();
        String sql = "SELECT COD, DESCRICAO, DT, CODUSR FROM EVENTO ORDER BY COD";
        Statement st = this.conexao.createStatement();
        ResultSet rs = st.executeQuery(sql);
        while (rs.next()) {
            Evento evt = new Evento();
            evt.setCod(rs.getInt("COD"));
            evt.setDescricao(rs.getString("DESCRICAO"));
            evt.setDt(rs.getDate("DT"));
            
            UsuarioDAO usrDAO = new UsuarioDAO(conexao);
            Usuario usr = new Usuario();
            usr.setCoduser(rs.getInt("CODUSR"));
            usr = usrDAO.retrieve(usr);
            evt.setCodusr(usr);
            lista.add(evt);
        }
        rs.close();
        st.close();
        return lista;
    }

    /**
     * Aplica os testes para as regras de negócio. 
     * @param evt Funcioanario a ser testado
     * @return true se o Funcionario atende as regras de negócio, ou false em caso contrário.
     */
    public boolean valida(Evento evt) {
        boolean ret = false;
        if (evt != null) {
            ret = true;
        }
        return ret;
    }
}
